#include <logger.h>

#include "modelmanger.h"
#include "iot_debug.h"
#include "rapidjson/tools.h"
#include "config.h"

using namespace rapidjson;
using namespace DC;


static bool loadModel(const char *filepath, ModelItems *items);

ModelManger *ModelManger::mgr()
{
    static ModelManger m;
    return &m;
}

ModelManger::ModelManger()
{

}

ModelManger::~ModelManger()
{
    clearNode();
}

void ModelManger::getModelNames(std::list<std::string> &names) const
{
    names.clear();
    for (auto it=map_node_.begin(); it!=map_node_.end(); it++)
        names.push_back(it->first);
}

const ModelItems *ModelManger::node(const char *model)
{
    if(model == NULL)
    {
        return nullptr;
    }
    auto it = map_node_.find(model);
    if (it == map_node_.end()) {
        ModelItems *items = new ModelItems;
        if (loadProfile(model, items)) {
            map_node_[model] = items;
            return items;
        }
        delete items;
        return nullptr;
    }
    return it->second;
}


void ModelManger::clearNode()
{
    for (auto it=map_node_.begin(); it!=map_node_.end(); it++) {
        if (it->second)
            delete it->second;
    }
    map_node_.clear();
}

const ModelItem *ModelManger::findItem(const ModelItems *items, const char *name)
{
    for (auto it=items->begin(); it!=items->end(); it++) {
        if (it->name.compare(name) == 0)
            return &(*it);
    }
    return nullptr;
}

bool ModelManger::loadProfile(const char *model_name, ModelItems *items)
{
    std::string filename("");
    filename = DATACENTERMODEL_PATH;
    filename += model_name;
    filename += ".json";
    log_info("try to load %s\n", filename.c_str());
    return loadModel(filename.c_str(), items);
}

bool loadModel(const char *filepath, ModelItems *items)
{
    Document doc;
    Value *body = nullptr;

    if (!::parseFile(filepath, doc))
        goto exitCode;

    body = getChild(doc, "body");
    if (!body || !body->IsArray())
        goto exitCode;

    for (auto it=body->Begin(); it!=body->End(); it++) {
        if (it->IsObject()) {
            ModelItem item;
            item.name = getString(it, "name", "");
            item.type = getString(it, "type", "");
            item.unit = getString(it, "unit", "");
            item.ratio = getString(it, "ratio", "1");
            item.deadzone = getString(it, "deadzone", "0");
            item.isReport = getString(it, "isReport", "0");
            item.userdefine = getString(it, "userdefine", "0");

            if (item.name.empty() || item.type.empty())
                goto exitCode;
            items->push_back(item);
        }
        else
            goto exitCode;
    }

    return true;
exitCode:
    log_info("load %s failed\n", filepath);
    return false;
}
